package edu.yctc.origin.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

import edu.yctc.origin.constant.ResultCode;
import edu.yctc.origin.dao.AuthorDAO;
import edu.yctc.origin.dao.BookDAO;
import edu.yctc.origin.dao.PressDAO;
import edu.yctc.origin.dao.StockDAO;
import edu.yctc.origin.entity.AuthorDO;
import edu.yctc.origin.entity.BookDO;
import edu.yctc.origin.entity.PressDO;
import edu.yctc.origin.entity.ResultDO;
import edu.yctc.origin.entity.StockDO;
import edu.yctc.origin.service.MetadataIService;
import edu.yctc.origin.vo.BookVO;

/**
 * 元数据管理业务层实现
 * 
 * @author 赵宜珺
 *
 */
@ComponentScan({"edu.yctc.origin.dao"})
@Service("metadataService")
public class MetadataServiceImpl implements MetadataIService {

    private final static Logger LOG = LoggerFactory.getLogger("serviceLogger");

    @Resource
    private BookDAO bookDAO;

    @Resource
    private PressDAO pressDAO;

    @Resource
    private StockDAO stockDAO;

    @Resource
    private AuthorDAO authorDAO;

    @Override
    public ResultDO<List<BookVO>> getBookVOsByName(String name) {
        if (StringUtils.isBlank(name)) {
            LOG.error("get bookVOs by name fail, parameter invalid, name={}", name);
            return new ResultDO<List<BookVO>>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID,
                null);
        }
        try {
            List<BookDO> bookDOs = bookDAO.getBookDOsByName(name);
            List<BookVO> bookVOs = new ArrayList<>();
            for (BookDO bookDO : bookDOs) {
                BookVO bookVO = new BookVO();
                bookVO.setId(bookDO.getId());
                bookVO.setName(bookDO.getName());
                bookVO.setNumber(bookDO.getNumber());
                bookVO.setAuthor(authorDAO.getAuthorDOById(bookDO.getAuthorId()).getName());
                bookVO.setPress(pressDAO.getPressDOById(bookDO.getPressId()).getName());
                bookVO.setStock(stockDAO.getStockDOByBookId(bookDO.getId()).getStock());
                bookVOs.add(bookVO);
            }
            LOG.info("get bookVOs by name success, name={}, bookVOs={}", name, bookVOs);
            return new ResultDO<List<BookVO>>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, bookVOs);
        } catch (Exception e) {
            LOG.error("get bookVOs by name error, name={}", name, e);
            return new ResultDO<List<BookVO>>(false, ResultCode.ERROR_SYSTEM_EXCEPTION,
                ResultCode.MSG_ERROR_SYSTEM_EXCEPTION, null);
        }
    }

    @Override
    public ResultDO<BookVO> getBookVOByBookId(long bookId) {
        if (bookId <= 0) {
            LOG.error("get bookVO by bookId fail, parameter invalid, bookId={}", bookId);
            return new ResultDO<BookVO>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
        }
        try {
            BookDO bookDO = bookDAO.getBookDOById(bookId);
            if (bookDO == null) {
                LOG.error("get bookVO by bookId fail, no such book, bookId={}", bookId);
                return new ResultDO<BookVO>(false, ResultCode.NO_SUCH_BOOK, ResultCode.MSG_NO_SUCH_BOOK, null);
            }
            BookVO bookVO = new BookVO();
            bookVO.setId(bookId);
            bookVO.setName(bookDO.getName());
            bookVO.setNumber(bookDO.getNumber());
            bookVO.setAuthor(authorDAO.getAuthorDOById(bookDO.getAuthorId()).getName());
            bookVO.setPress(pressDAO.getPressDOById(bookDO.getPressId()).getName());
            bookVO.setStock(stockDAO.getStockDOByBookId(bookId).getStock());
            LOG.info("get bookVO by bookId success, bookId={}, bookVO={}", bookId, bookVO);
            return new ResultDO<BookVO>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, bookVO);
        } catch (Exception e) {
            LOG.error("get bookVO by bookId error, bookId={}", bookId, e);
            return new ResultDO<BookVO>(false, ResultCode.ERROR_SYSTEM_EXCEPTION, ResultCode.MSG_ERROR_SYSTEM_EXCEPTION,
                null);
        }
    }

    @Override
    public ResultDO<Void> deleteBookById(long id) {
        if (id <= 0) {
            LOG.error("delete book by id fail, parameter invalid, id={}", id);
            return new ResultDO<Void>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID);
        }
        try {
            // 删除book和库存
            bookDAO.deleteById(id);
            stockDAO.deleteByBookId(id);
            LOG.info("delete book by id success, id={}", id);
            return new ResultDO<Void>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS);
        } catch (Exception e) {
            LOG.error("delete book by id, id={}", id, e);
            return new ResultDO<Void>(false, ResultCode.ERROR_SYSTEM_EXCEPTION, ResultCode.MSG_ERROR_SYSTEM_EXCEPTION);
        }
    }

    @Override
    public ResultDO<Void> modifyBook(BookVO bookVO) {
        if (bookVO.getId() <= 0 || bookVO.getStock() < 0 || StringUtils.isBlank(bookVO.getAuthor())
            || StringUtils.isBlank(bookVO.getName()) || StringUtils.isBlank(bookVO.getNumber())
            || StringUtils.isBlank(bookVO.getPress())) {
            LOG.error("modify book fail, bookVO={}", bookVO);
            return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID);
        }
        try {
            // 更新
            BookDO bookDO = bookDAO.getBookDOById(bookVO.getId());
            bookDO.setName(bookVO.getName());
            bookDO.setNumber(bookVO.getNumber());
            String author = bookVO.getAuthor();
            String press = bookVO.getPress();
            int stock = bookVO.getStock();
            // 判断数据库中查是否存在该作者
            AuthorDO authorDO = authorDAO.getAuthorDOByName(author);
            // 没找到则插入
            if (authorDO == null) {
                authorDO = new AuthorDO();
                authorDO.setName(author);
                authorDAO.insert(authorDO);
            }
            // 判断数据库中是否存在该出版社
            PressDO pressDO = pressDAO.getPressDOByName(press);
            if (pressDO == null) {
                pressDO = new PressDO();
                pressDO.setName(press);
                pressDAO.insert(pressDO);
            }
            BookDO check = bookDAO.getBookDOByNameAndNumberAndPressIdAndAuthorId(bookVO.getName(), bookVO.getNumber(),
                pressDO.getId(), authorDO.getId());
            // 已经有该书(不是单纯修改库存)，禁止修改
            if (check != null && check.getId() != bookVO.getId()) {
                LOG.error("modify book by id fail, already exist this book to modify, bookVO={}, check={}", bookVO,
                    check);
                return new ResultDO<>(false, ResultCode.DB_ERROR, ResultCode.MSG_DB_ERROR);
            }
            bookDO.setAuthorId(authorDO.getId());
            bookDO.setPressId(pressDO.getId());
            bookDAO.update(bookDO);
            // 更新库存
            StockDO stockDO = stockDAO.getStockDOByBookId(bookVO.getId());
            stockDO.setStock(stock);
            stockDAO.update(stockDO);
            LOG.info("modify book success, bookVO={}, bookDO={}", bookVO, bookDO);
            return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS);
        } catch (Exception e) {
            LOG.error("modify book error, bookVO={}", bookVO, e);
            return new ResultDO<>(false, ResultCode.ERROR_SYSTEM_EXCEPTION, ResultCode.MSG_PARAMETER_INVALID);
        }
    }

}
